package com.appspot.eusms.database;

import android.util.Log;
import android.util.Xml;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;

public class XmlBackup {

    private static final String PROTOCOL = "protocol";
    private static final String ADDRESS = "address";
    private static final String DATE = "date";
    private static final String TYPE = "type";
    private static final String SUBJECT = "subject";
    private static final String BODY = "body";
    private static final String SERVICE_CENTER = "service_center";
    private static final String READ = "read";
    private static final String STATUS = "status";

    private final XmlPullParser parser;

    public XmlBackup(String path) throws XmlPullParserException, FileNotFoundException {
        this.parser = Xml.newPullParser();
        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
        parser.setInput(new FileInputStream(path), null);
    }

    public XmlBackupItem getNext() throws IOException, XmlPullParserException {
        while (parser.next() != XmlPullParser.END_DOCUMENT) {
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }

            String name = parser.getName();

            if (!name.equals("sms")) {
                continue;
            }

            int attributeCount = parser.getAttributeCount();

            if (attributeCount <= 0) {
                continue;
            }

            XmlBackupItem item = new XmlBackupItem();

            for (int i = 0; i < attributeCount; i++) {
                String attributeName = parser.getAttributeName(i);

                if (attributeName.equals(PROTOCOL))
                    item.protocol = Integer.parseInt(parser.getAttributeValue(i));
                else if (attributeName.equals(ADDRESS)) item.address = parser.getAttributeValue(i);
                else if (attributeName.equals(DATE))
                    item.date = Long.parseLong(parser.getAttributeValue(i));
                else if (attributeName.equals(TYPE))
                    item.type = Integer.parseInt(parser.getAttributeValue(i));
                else if (attributeName.equals(SUBJECT)) item.subject = parser.getAttributeValue(i);
                else if (attributeName.equals(BODY)) item.body = parser.getAttributeValue(i);
                else if (attributeName.equals(SERVICE_CENTER))
                    item.serviceCenter = parser.getAttributeValue(i);
                else if (attributeName.equals(READ))
                    item.read = Integer.parseInt(parser.getAttributeValue(i));
                else if (attributeName.equals(STATUS))
                    item.status = Integer.parseInt(parser.getAttributeValue(i));
            }

            return item;
        }

        return null;
    }

    public static class XmlBackupItem {
        private int protocol;
        private String address;
        private long date;
        private int type;
        private String subject;
        private String body;
        private String serviceCenter;
        private int read;
        private int status;

        public XmlBackupItem() {
        }

        public XmlBackupItem(int protocol, String address, long date, int type, String subject,
                             String body, String serviceCenter, int read, int status) {
            this.protocol = protocol;
            this.address = address;
            this.date = date;
            this.type = type;
            this.subject = subject;
            this.body = body;
            this.serviceCenter = serviceCenter;
            this.read = read;
            this.status = status;
        }

        public int getProtocol() {
            return protocol;
        }

        public String getAddress() {
            return address;
        }

        public long getDate() {
            return date;
        }

        public int getType() {
            return type;
        }

        public String getSubject() {
            return subject;
        }

        public String getBody() {
            return body;
        }

        public String getServiceCenter() {
            return serviceCenter;
        }

        public int getRead() {
            return read;
        }

        public int getStatus() {
            return status;
        }
    }

    public static class Writer {

        private BufferedWriter writer;
        private XmlSerializer serializer;

        public Writer(String path, int count) throws IOException {
            this.writer = new BufferedWriter(new FileWriter(path));
            this.serializer = Xml.newSerializer();

            this.serializer.setOutput(writer);
            this.serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
            this.serializer.startDocument("UTF-8", true);
            this.serializer.startTag("", "smses");
            this.serializer.attribute("", "count", count + "");
        }

        public void writeItem(XmlBackupItem item) throws IOException {
            this.serializer.startTag("", "sms");
            this.serializer.attribute("", "protocol", item.getProtocol() + "");
            this.serializer.attribute("", "address", item.getAddress());
            this.serializer.attribute("", "date", item.getDate() + "");
            this.serializer.attribute("", "type", item.getType() + "");
            this.serializer.attribute("", "subject", item.getSubject() + "");
            try {
                this.serializer.attribute("", "body", item.getBody() + "");
            } catch (IllegalArgumentException ise) {
                // XXX - Fucking Android. Their serializer includes a bug that doesn't
                // handle some unicode characters correctly.
                Log.w("XmlBackup", ise);
            }
            this.serializer.attribute("", "toa", null + "");
            this.serializer.attribute("", "sc_toa", null + "");
            this.serializer.attribute("", "service_center", item.getServiceCenter() + "");
            this.serializer.attribute("", "read", item.getRead() + "");
            this.serializer.attribute("", "status", item.getStatus() + "");
            this.serializer.attribute("", "locked", "0");
            this.serializer.endTag("", "sms");
        }

        public void close() throws IOException {
            this.serializer.endTag("", "smses");
            this.serializer.endDocument();
        }
    }
}
